package com.concurrent.chapter6.concurrent01;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyCallable implements Callable<String> {
	private String username;
	private long sleepValue;
	
	public MyCallable(String username, long sleepValue) {
		super();
		this.username = username;
		this.sleepValue = sleepValue;
	}

	@Override
	public String call() throws Exception {
		System.out.println(username + "  " + Thread.currentThread().getName() + System.currentTimeMillis());
		Thread.sleep(sleepValue);
		return "return " + username;
	}

	public static void main(String[] args) {
		try {
			MyCallable callable1 = new MyCallable("username1", 5000);
			MyCallable callable2 = new MyCallable("username2", 4000);
			MyCallable callable3 = new MyCallable("username3", 3000);
			MyCallable callable4 = new MyCallable("username4", 2000);
			MyCallable callable5 = new MyCallable("username5", 1000);
			
			List<Callable<String>> callables = new ArrayList<>();
			callables.add(callable1);
			callables.add(callable2);
			callables.add(callable3);
			callables.add(callable4);
			callables.add(callable5);

			int corePoolSize = 5;
			int maximumPoolSize = 10;
			int keepAliveTime = 5;
			TimeUnit unit = TimeUnit.SECONDS;
			LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
			ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
			CompletionService completionService = new ExecutorCompletionService<>(executor);
			for (int i = 0; i < 5; i++) {
				completionService.submit(callables.get(i));
			}
			for (int i = 0; i < 5; i++) {
				System.out.println(completionService.take().get() + " -- " + System.currentTimeMillis());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
